home *** CD-ROM | disk | FTP | other *** search
- /*________________________________________________________
-
- File: UserItems.c
-
- C code for a printing extension that shows how
- to handle hits and updates for userItems in panels.
-
- Dave Hersey
- Apple Developer Technical Support
-
- 6/06/93 - dmh - Created.
- 9/07/93 - dmh - Updated for b2.
- 12/18/93 - dmh - Updated for b3.
- 3/22/94 - dmh - Updated for b4.
-
- (Note: all functions are in the Mark menu.)
-
- __________________________________________________________*/
-
- #include "UserItems.h"
-
-
- MyGlobalRec gl; // Global data used by our extension.
-
-
- /*******************************************************************
- InitGlobalData is used to initialize any global data we need to
- in our initialize message override. It's critical that you do
- things this way, rather than access the data in the same scope
- that you call NewMessageGlobals. Otherwise, some compilers
- will give you code that references an invalid a5 world.
-
- ********************************************************************/
-
- OSErr InitGlobalData()
- {
- // Initialize any global data here.
-
- gl.panelPict = nil;
- return noErr;
- }
-
-
- /*******************************************************************
- NewInitialize is our override for the Initialize message. In
- here, you shouldn't initialize anything directly-- call
- InitGlobalData for that. Once you create the A5 world with
- NewMessageGlobals, you can access your global data just like
- you were an app. Whenever you're called, your global data will
- be valid.
-
- ********************************************************************/
-
- OSErr NewInitialize()
- {
- OSErr err;
-
- // Create an A5 world, and initialize our global data.
-
- err = NewMessageGlobals(A5Size(), A5Init);
-
- if (!err) err = InitGlobalData();
-
- return err;
- }
-
-
- /*******************************************************************
- NewShutDown is our override for the GXShutDown message. We
- simply throw away our a5 world.
-
- ********************************************************************/
-
- OSErr NewShutDown()
- {
- DisposeMessageGlobals();
- return noErr;
- }
-
-
- /*******************************************************************
- NewJobPrintDialog is our override for GXJobPrintDialog. All
- we do is set up our panel and then forward the message.
-
- ********************************************************************/
-
- OSErr NewJobPrintDialog(gxDialogResult *dlogResult)
- {
- OSErr err;
-
- err = SetUpPrintPanel();
-
- if (!err)
- err = Forward_GXJobPrintDialog(dlogResult);
-
- return err;
- }
-
-
- /*******************************************************************
- NewHandlePanelEvent is our override for GXHandlePanelEvent. If
- the event is one of ours, we handle it, otherwise we just
- forward it down the chain.
-
- ********************************************************************/
-
- OSErr NewHandlePanelEvent(gxPanelInfoRecord *panelInfo)
- {
- OSErr err = noErr;
- GrafPtr oldPort;
- DialogPtr pDlg;
- short oldResFile;
-
- // Get a pointer to the dialog, save our current grafPort,
- // and set us to the dialog's port.
-
- pDlg = panelInfo->pDlg;
- GetPort(&oldPort);
- SetPort(pDlg);
-
- switch (panelInfo->panelEvt)
- {
- case gxPanelOpenEvt: // Initialize and draw
- // Load the user item picture.
- oldResFile = CurResFile();
- UseResFile(GXGetMessageHandlerResFile());
- gl.panelPict = GetPicture(r_ExtensionPanel);
- UseResFile(oldResFile);
- break;
-
- case gxPanelCloseEvt: // Your panel is going away (panel switch,
- // confirm or cancel)
- if (gl.panelPict)
- ReleaseResource((Handle) gl.panelPict);
-
- break;
- }
-
- // Restore the original port as we leave.
-
- SetPort(oldPort);
- return err;
- }
-
-
- /*******************************************************************
- NewFilterPanelEvent is a routine to filter update events in our
- panel, and update our userItems accordingly.
-
- ********************************************************************/
-
- OSErr NewFilterPanelEvent(gxPanelInfoRecord *panelInfo, Boolean *returnImmed)
- {
- OSErr err = noErr;
- DialogPtr pDlg;
- WindowPtr theWindow;
- short thePart, theItem;
- Point thePt;
-
- // Get a pointer to the dialog, save our current grafPort,
- // and set us to the dialog's port.
-
- pDlg = panelInfo->pDlg;
-
- switch (panelInfo->panelEvt)
- {
- case gxPanelFilterEvt:
-
- switch (panelInfo->theEvent->what)
- {
- case updateEvt: // look for, and handle, our update events.
-
- if ((WindowPtr) panelInfo->theEvent->message == pDlg)
- err = HandlePanelUpdate(pDlg, panelInfo);
-
- break;
-
- case mouseDown: // look for our dialog item hits.
- // If we're not the front window, ignore hits.
-
- require((pDlg == FrontWindow()), NotFrontWindow);
- thePart = FindWindow(panelInfo->theEvent->where, &theWindow);
- require(((theWindow == pDlg) && (thePart == inContent)), NotForUs);
-
- thePt = panelInfo->theEvent->where;
- GlobalToLocal(&thePt);
- theItem = FindDItem(pDlg, thePt);
-
- // FindDItem == -1 if the point lies outside the dialog.
- // Unless theItem == -1, go handle the hit.
-
- if (theItem != -1)
- err = HandlePanelHit(pDlg, panelInfo, theItem +1, returnImmed);
-
- NotForUs:
- NotFrontWindow:
- break;
- }
- }
-
- return err;
- }
-
-
- /*******************************************************************
- HandlePanelUpdate is a routine to update our panel's userItems.
- Note that we don't pass this routine to the Dialog Manager,
- we only get here by way of our panel event handler. This
- assures that we can access our global data, and that our
- resource file is open. In this example, we draw from a global
- PicHandle, to show that our globals are intact.
-
- NOTE: With the exception of the code below that's marked:
-
- "YOU SHOULD CHANGE THE FOLLOWING…"
-
- you can just use this code verbatim, regardless of the number
- or purpose of your dialog's userItems.
-
- ********************************************************************/
-
- OSErr HandlePanelUpdate(DialogPtr theDialog, gxPanelInfoRecord *panelInfo)
- {
- GrafPtr oldPort;
- OSErr err;
- Rect theClipRect, myUserItemRect;
- RgnHandle tempRgn, oldVis;
- Point top;
- short dx, dy, itemKind;
- Handle itemHdl;
-
- // Create a new region handle. If we can't do that, return an error.
-
- tempRgn = NewRgn();
- require_action(tempRgn, CanNotCreateRgn, err = MemError(););
-
-
- // Copy the window's update region to our temporary region handle,
- // then adjust the region so that it's correctly aligned with our
- // window. Finally, intersect this region with the window's visRgn.
-
- CopyRgn(((DialogPeek) theDialog)->window.updateRgn, tempRgn);
- top = *(Point *) &(*tempRgn)->rgnBBox.top;
- GlobalToLocal(&top);
- dx = (*tempRgn)->rgnBBox.left - top.h;
- dy = (*tempRgn)->rgnBBox.top - top.v;
- OffsetRgn(tempRgn, -dx, -dy);
- SectRgn(theDialog->visRgn, tempRgn, tempRgn);
-
- nrequire((err = MemError()), CanNotCopyRgn);
-
-
- // Now, get the various bounds rects of your userItems and
- // see if any fall within the update area. If not, don't
- // bother drawing anything.
- //
- // NOTE: YOU SHOULD CHANGE THE FOLLOWING CODE to account for
- // for all of your userItems. We only have one userItem in
- // this example.
-
- GetDItem(theDialog, panelInfo->itemCount + kMyUserItem, &itemKind,
- &itemHdl, &myUserItemRect);
-
- theClipRect = (*tempRgn)->rgnBBox;
-
- if (SectRect(&myUserItemRect, &theClipRect, &theClipRect))
- {
-
- // Save the current visRgn, and store our temporary region as the new
- // visRgn. This is similar to what happens when BeginUpdate is called.
- // When we draw, only pixels that fall in the update area (clipped to
- // the window's clipRgn) will be drawn. This keeps us from doing
- // unnecessary redrawing, which would cause flashing and wasted cycles.
-
- oldVis = theDialog->visRgn;
- theDialog->visRgn = tempRgn;
-
-
- // Save the current port, change it to the dialog's port, draw any
- // userItems that need updating, validate their areas and restore
- // the old visRgn and grafPort.
- //
- // NOTE: YOU SHOULD CHANGE THE FOLLOWING CODE to redraw and validate
- // any of your userItems which intersect the update region. We only
- // have one userItem in this example.
-
- GetPort(&oldPort);
- SetPort(theDialog);
-
- DrawPicture(gl.panelPict, &myUserItemRect);
- ValidRect(&myUserItemRect);
-
- theDialog->visRgn = oldVis;
- SetPort(oldPort);
- }
-
- // Throw away our temporary region, and return any error.
-
- CanNotCopyRgn:
- DisposeRgn(tempRgn);
-
-
- CanNotCreateRgn:
-
- return err;
- }
-
-
- /*******************************************************************
- HandlePanelHit is a routine to handle mouse hits in a panel's
- userItem fields. In this sample, we simply invert our userItem
- whenever it's clicked in, and set returnImmed to true,
- indicating that this event has been processed.
-
- ********************************************************************/
-
- OSErr HandlePanelHit(DialogPtr theDialog, gxPanelInfoRecord *panelInfo,
- short theItem, Boolean *returnImmed)
- {
- GrafPtr oldPort;
- OSErr err = noErr;
- short itemKind;
- Rect itemRect;
- Handle itemHdl;
-
- // Save the current grafPort, set the current port to the dialog,
- // handle our panel hits, and restore the current port.
-
- GetPort(&oldPort);
- SetPort(theDialog);
-
- switch (theItem - panelInfo->itemCount)
- {
-
- // Flash our userItem if it's hit.
-
- case kMyUserItem:
-
- GetDItem(theDialog, theItem, &itemKind, &itemHdl, &itemRect);
- InvertRect(&itemRect);
- while (StillDown());
- InvertRect(&itemRect);
-
- *returnImmed = true;
- break;
-
- /* Code for handling other userItems would follow.
- .
- .
- .
- */
-
- }
-
- SetPort(oldPort);
- return err;
- }
-
-
- /*******************************************************************
- SetUpPrintPanel sets up our print panel, adding a default
- ExtensionCollection item to the job collection. This
- collection item has the values we'll use to set up our panel's
- controls.
-
- ********************************************************************/
-
- OSErr SetUpPrintPanel()
- {
- OSErr err;
- gxPanelSetupRecord panelSetupRec;
- ExtensionCollection extConfig;
-
- // Try to find our collection item.
-
- err = GetCollectionItem(GXGetJobCollection(GXGetJob()),
- kExtensionCollectionType,
- gxPrintingTagID,
- nil,
- &extConfig);
-
-
- // If we don't have an item in the job collection yet, store our default
- // settings in it.
-
- if (err == collectionItemNotFoundErr)
- {
- extConfig.extTurnedOn = kDefaultSetting;
-
- err = AddCollectionItem(GXGetJobCollection(GXGetJob()),
- kExtensionCollectionType,
- gxPrintingTagID,
- sizeof(ExtensionCollection),
- &extConfig);
-
- nrequire(err, HaveCollectionMgrError);
- }
-
-
- // Now, set up the panel.
-
- panelSetupRec.panelResId = r_ExtensionPanel; // which panel resource?
- panelSetupRec.resourceRefNum = GXGetMessageHandlerResFile(); // where is it?
- panelSetupRec.refCon = 0; // we don't use this.
- panelSetupRec.panelKind = gxExtensionPanel; // This is an extension panel.
-
- err = GXSetupDialogPanel(&panelSetupRec);
-
-
- HaveCollectionMgrError:
-
- return err;
- }
-